﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using FantomUI.Util;
using ft = Fantom;


namespace FantomUI.Controls
{
	/// <summary>
	/// 设计器。
	/// </summary>
	public class Designer : Control
	{
		#region enum

		// 鼠标操作状态字。
		private enum MouseCommandType
		{
			None,
			Movement,
			Resize,
			Rotation,
			Selection,
		}
		#endregion

		#region delegate & events

		public delegate void SelectionHandler(Rect rect);

		/// <summary>
		/// 在选择完成时触发该事件。
		/// </summary>
		public event SelectionHandler OnSelectionCompleted;
		#endregion

		#region properties

		// 选择框所在图层。
		private Border _selectionFrameBorder = null;

		// 选择框所在图层。
		private Border SelectionFrameBorder
		{
			get
			{
				if (_selectionFrameBorder == null)
				{

					_selectionFrameBorder = this.GetTemplateChild("PART_Selection") as Border;
				}

				return _selectionFrameBorder;
			}
		}

		// 选择框。
		private SelectionFrame _selectionFrame = null;

		// 选择框的起点。
		private Point _startPoint;

		// 设计器图层。
		private DesignerCanvas _designerCanvas = null;
		private DesignerCanvas DesignerCanvas
		{
			get
			{
				if (_designerCanvas == null)
				{
					_designerCanvas = this.GetTemplateChild("PART_ItemsContainer") as DesignerCanvas;
					_designerCanvas.Designer = this;

				}

				return _designerCanvas;
			}
		}


		// 选框对象。
		private AdjustmentFrameLayer _adjustmentFrameLayer = null;
		private AdjustmentFrameLayer AdjustmentFrameLayer
		{
			get
			{
				if (_adjustmentFrameLayer == null)
				{
					_adjustmentFrameLayer = this.GetTemplateChild("PART_Adjustment") as AdjustmentFrameLayer;
					_adjustmentFrameLayer.Designer = this;
				}

				return _adjustmentFrameLayer;
			}
		}

		private UIPresentation _uipresentation;

		// 当前画布表示的图形集合。
		private ft.IShapes _shapes;

		// 图形对象。
		private List<UIShape> _uiShapes;

		// 图形字典。
		private Dictionary<ft.IShape, UIShape> _shapeDic;


		// 命令状态。
		private MouseCommandType _command = MouseCommandType.None;

		private int _repeatCounter = 0;

		#endregion

		#region dependency properties

		// 画布高度。
		public double CanvasHeight
		{
			get { return (double)GetValue(CanvasHeightProperty); }
			set { SetValue(CanvasHeightProperty, value); }
		}

		// Using a DependencyProperty as the backing store for CanvasHeight.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty CanvasHeightProperty =
			DependencyProperty.Register("CanvasHeight", typeof(double), typeof(Designer), new PropertyMetadata(0d));


		// 画布宽度。
		public double CanvasWidth
		{
			get { return (double)GetValue(CanvasWidthProperty); }
			set { SetValue(CanvasWidthProperty, value); }
		}

		// Using a DependencyProperty as the backing store for CanvasWidth.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty CanvasWidthProperty =
			DependencyProperty.Register("CanvasWidth", typeof(double), typeof(Designer), new PropertyMetadata(0d));




		#endregion

		#region ctors

		public Designer()
		{
			this.Initialized += Designer_Initialized;
			// this.MouseMove += Designer_MouseMove;
			// this.MouseLeftButtonUp += Designer_MouseLeftButtonUp;
			this.OnSelectionCompleted += Designer_OnSelectionCompleted;
			this.MouseLeftButtonDown += Designer_MouseLeftButtonDown;

			// 添加全局监听的选框绘制事件。
			Mouse.AddMouseMoveHandler(Application.Current.MainWindow, Designer_MouseMove);
			Mouse.AddPreviewMouseUpHandler(Application.Current.MainWindow, Designer_MouseUp);
			Mouse.AddMouseLeaveHandler(Application.Current.MainWindow, Designer_Leave);

			Keyboard.AddPreviewKeyDownHandler(Application.Current.MainWindow, Designer_KeyDown);
		}

		static Designer()
		{
			DefaultStyleKeyProperty.OverrideMetadata(
				typeof(Designer),
				new FrameworkPropertyMetadata(typeof(Designer)));
		}

		#endregion

		#region events


		// 初始化完成时。
		private void Designer_Initialized(object sender, EventArgs e)
		{

		}

		// 设计器获得键入消息。
		private void Designer_KeyDown(object sender, KeyEventArgs e)
		{
			e.Handled = true; // 禁止事件传递。
			if (_shapes == null) return;

			if (_shapes.Selection.Count() != 0)
			{
				var distance = 1;
				if (e.IsRepeat)
					_repeatCounter++;
				else
					_repeatCounter = 0;

				if (_repeatCounter > 30)
					distance = 4;
				else if (_repeatCounter > 20)
					distance = 3;
				else if (_repeatCounter > 10)
					distance = 2;

				Vector2 vector2 = new Vector2() { X = 0, Y = distance };

				if (e.Key == Key.Left)
					vector2 = new Vector2() { X = -distance, Y = 0 };
				else if (e.Key == Key.Right)
					vector2 = new Vector2() { X = distance, Y = 0 };
				else if (e.Key == Key.Up)
					vector2 = new Vector2() { X = 0, Y = -distance };
				else if (e.Key == Key.Down)
					vector2 = new Vector2() { X = 0, Y = distance };
				else
					return;

				foreach (ft.IShape shape in _shapes.Selection)
				{
					_shapeDic[shape].RelativeMove(vector2);
					// _shapeDic[shape].FrameInfo.left = vector2.X;;
				}

			}

		}

		// 鼠标按下时，选中当前的图形对象。
		private void Designer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			if (_shapes == null) return;

			var point = Mouse.GetPosition(this);

			var rst = VisualTreeHelper.HitTest(this, point);
			var target = rst.VisualHit;

			_startPoint = point;

			if (target is PresentationVisual)
			{
				var visual = target as PresentationVisual;
				var uishape = _uiShapes.Find((uishp) =>
				{
					return uishp.PresentationVisual == visual;
				});

				if (uishape.Source.IsSelected == false)
					_shapes.Select(uishape.Source);

				foreach (ft.IShape shape in _shapes.Selection)
				{
					_shapeDic[shape].IsMoving = true;
				}

				_command = MouseCommandType.Movement;


			}
			else if (target is BaseStrokeFrameVisual)
			{
				var visual = target as BaseStrokeFrameVisual;
				var uishape = visual.UIShape;

				if (uishape.Source.IsSelected == false)
					_shapes.Select(uishape.Source);

				foreach (ft.IShape shape in _shapes.Selection)
				{
					_shapeDic[shape].IsMoving = true;
				}

				_command = MouseCommandType.Movement;

			}
			else
			{

				_shapes.UnSelectAll(); // 此处用于撤销选中。

				_selectionFrame = new SelectionFrame(point);
				SelectionFrameBorder.Child = _selectionFrame; // 为选框容器放入新建的选框对象。
				_command = MouseCommandType.Selection;
			}
		}

		// 鼠标移动与拖动时。
		private void Designer_MouseMove(object sender, MouseEventArgs e)
		{
			if (_shapes == null) return;
			var point = Mouse.GetPosition(this);

			var rst = VisualTreeHelper.HitTest(this, point);
			var target = rst?.VisualHit;

			// 移动 + 按下 => 拖拽中
			if (e.LeftButton == MouseButtonState.Pressed)
			{

				switch (_command)
				{
					case MouseCommandType.None:
						break;
					case MouseCommandType.Movement:
						Mouse.OverrideCursor = Cursors.SizeAll;
						_shape_OnDragMove(point);
						break;
					case MouseCommandType.Resize:
						break;
					case MouseCommandType.Rotation:
						break;
					case MouseCommandType.Selection:
						if (SelectionFrameBorder.Child != null)
							_selectionFrame.Rect = new Rect(_startPoint, point);

						break;
					default:
						break;
				}

			}
			else
			{
				if (target is BaseStrokeFrameVisual)
					Mouse.OverrideCursor = Cursors.SizeAll;
				else
					Mouse.OverrideCursor = Cursors.Arrow;
			}

		}


		// 左键弹出时。
		private void Designer_MouseUp(object sender, MouseButtonEventArgs e)
		{
			if (_shapes == null) return;
			Mouse.OverrideCursor = Cursors.Arrow;
			if (_command == MouseCommandType.Selection && this._selectionFrame != null)
			{
				SelectionFrameBorder.Child = null;
				OnSelectionCompleted?.Invoke(this._selectionFrame.Rect);
				this._selectionFrame = null;
			}
			else if (_command == MouseCommandType.Movement)
			{
				var point = Mouse.GetPosition(this);
				Vector2 vector2 = point.Sub(_startPoint);
				foreach (ft.IShape shape in _shapes.Selection)
				{
					shape.Transform.IncreaseOffset(vector2.X, vector2.Y);
					_shapeDic[shape].IsMoving = false;
				}
			}

			_command = MouseCommandType.None;

		}

		// 鼠标离开窗体时触发该事件。
		private void Designer_Leave(object sender, MouseEventArgs e)
		{
			if (_shapes == null) return;
			_command = MouseCommandType.None;
			SelectionFrameBorder.Child = null;
			if (this._selectionFrame != null)
			{
				OnSelectionCompleted?.Invoke(this._selectionFrame.Rect);
				this._selectionFrame = null;
			}

		}


		// 选择完成时触发该事件，为linq选中事件。
		private void Designer_OnSelectionCompleted(Rect rect)
		{
			if (_shapes == null) return;
			rect = new Rect(
				rect.Left - (ActualWidth - DesignerCanvas.ActualWidth) / 2,
				rect.Top - (ActualHeight - DesignerCanvas.ActualHeight) / 2,
				rect.Width, rect.Height);
			// MessageBox.Show(string.Format("{0}\n{1}\n{2}\n{3}", rect.Left, rect.Right, rect.Top, rect.Bottom));

			var shps =
				from shp in _uiShapes
				where shp.IsInSelectionFrame(rect)
				select shp.Source;

			_shapes.Select(shps);

		}


		// 当图形集合改变时。
		private void _shapes_OnSelectionChanged(ft.ISelection sender, ft.SelectionEventArgs args)
		{
			foreach (ft.IShape shape in args.AdditionRange)
			{
				_shapeDic[shape].ShowAdjustmentFrame();
			}
		}

		// 当全部选中时。
		private void _shapes_OnSelectAll(ft.ISelection sender, IEnumerable<ft.ISelectable> changes)
		{
			foreach (var shape in _uiShapes)
			{
				shape.ShowAdjustmentFrame();
			}
		}

		// 当全部解除选中时。
		private void _shapes_LostSelectAll(ft.ISelection sender, IEnumerable<ft.ISelectable> changes)
		{

			ClearAllSelectionScaleFrame();
		}


		// 当鼠标移动拖动位移时。
		private void _shape_OnDragMove(Point point)
		{
			Vector2 vector2 = point.Sub(_startPoint);
			foreach (ft.IShape shape in _shapes.Selection)
			{
				_shapeDic[shape].RelativeMove(vector2);
				// _shapeDic[shape].FrameInfo.left = vector2.X;;
			}
		}

		#endregion

		#region methods

		/// <summary>
		/// 载入图形。
		/// </summary>
		/// <param name="shapes"></param>
		public void Load(UIPresentation uipres, ft.IShapes shapes)
		{
			_uipresentation = uipres;

			if (_shapes != null)
			{
				Fresh();
			}


			_shapeDic = new Dictionary<ft.IShape, UIShape>();
			_uiShapes = new List<UIShape>();

			_shapes = shapes;

			foreach (var shape in shapes)
			{
				var uishape = new UIShape(_uipresentation, DesignerCanvas, AdjustmentFrameLayer, shape);
				_shapeDic.Add(shape, uishape);
				_uiShapes.Add(uishape);
			}



			// TODO _shapes 全部选中与全部取消选中。
			_shapes.OnSelectionChanged += _shapes_OnSelectionChanged;
			_shapes.OnSelectAll += _shapes_OnSelectAll;
			_shapes.LostSelectAll += _shapes_LostSelectAll;



		}


		/// <summary>
		/// 清除全部选框。
		/// </summary>
		private void ClearAllSelectionScaleFrame()
		{
			foreach (var shape in _uiShapes)
			{
				shape.HideAdjustmentFrame();
			}
		}


		/// <summary>
		/// 全部选中。
		/// </summary>
		public void SelectAll()
		{
			_shapes.SelectAll();
		}

		/// <summary>
		/// 全部取消选中。
		/// </summary>
		public void UnSelectAll()
		{
			_shapes.UnSelectAll();
		}


		/// <summary>
		/// 刷新画布。
		/// </summary>
		private void Fresh()
		{
			_shapes.UnSelectAll();
			_adjustmentFrameLayer.Clear();
			_designerCanvas.Clear();
		}

		#endregion

	}
}
